﻿using System.Globalization;
using System.Runtime.CompilerServices;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;

namespace WssUtils
{
    public class MyRandom : Singleton<MyRandom>
    {
        private System.Random random = new System.Random();

        public void Test()
        {
            //设置随机数种子
            random = new System.Random(1000);
            string str = "";
            for (int i = 0; i < 10; i++)
            {
                str += Range(1, 100) + ",";
            }
            Debug.Log(str);
        }


        /// <summary>
        /// 设置种子，并且初始化随机种子
        /// </summary>
        /// <param name="speed"></param>
        static public void SetSeed(int speed)
        {
            Instance.random = new System.Random(speed);
        }

        static public void ResetSeed()
        {
            Instance.random = new System.Random();
        }

        /// <summary>
        /// 随机整型
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        static public int Range(int min, int max)
        {
            return Instance.random.Next(min, max);
        }

        static public float Range(float min, float max)
        {
            var r = Instance.random.NextDouble();
            return (float)(r * (max - min) + min);
        }

        static public bool Bool()
        {
            return Range(0, 1.0f) > 0.5f;
        }

        /// <summary>
        /// 获取不重复的ID编号
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public static int[] GetNoRepeatIdList(int size = 1, int min = 0, int max = int.MaxValue)
        {
            var cache = new List<int>();
            int RmNum = size;
            for (int i = 0; cache.Count < RmNum; i++)
            {
                int nValue = Range(min, max);
                if (!cache.Contains(nValue) && nValue != 0)
                {
                    cache.Add(nValue);
                }
            }
            return cache.ToArray();
        }


        

        public static string String(int codeLength)
        {
            //组成字符串的字符集合  0-9数字、大小写字母
            string chars = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,P,P,Q,R,S,T,U,V,W,X,Y,Z";

            string[] charArray = chars.Split(new Char[] { ',' });
            string code = "";
            int temp = 0;//记录上次随机数值，尽量避避免生产几个一样的随机数  
            System.Random rand = null;
            //采用一个简单的算法以保证生成随机数的不同  
            for (int i = 1; i < codeLength + 1; i++)
            {
                if (temp != -1)
                {
                    rand = new System.Random(i * temp * unchecked((int)DateTime.Now.Ticks));//初始化随机类  
                }
                int t = rand.Next(61);
                if (temp == t)
                {
                    return String(codeLength);//如果获取的随机数重复，则递归调用  
                }
                temp = t;//把本次产生的随机数记录起来  
                code += charArray[t];//随机数的位数加一  
            }
            return code;
        }


        public static int WeightIndex(IList<int> weights, int limitCount = 0)
        {
            int count = weights.Count;
            if (limitCount > 0) count = Mathf.Clamp(count, 0, limitCount); //限制 范围
            int sum = 0;
            for (int i = 0; i < count; i++)
            {
                sum += weights[i];
            }

            int number_rand = Range(1, sum + 1);
            int sum_temp = 0;

            for (int i = 0; i < count; i++)
            {
                sum_temp += weights[i];
                if (number_rand <= sum_temp)
                {
                    return i;
                }
            }

            return -1;
        }

        /// <summary>
        ///  获得一个数组打乱后的结果 (复制)
        ///  TODO 修改减少 new List 的步骤
        /// </summary>
        /// <param name="inputList">输入的数组</param>
        /// <typeparam name="T">数组类型</typeparam>
        /// <returns>输出的数组</returns>
        public static void ShuffleSelf<T>(IList<T> inputList)
        {
            T[] copyArray = inputList.ToArray();
            List<T> copyList = new List<T>(copyArray);
            inputList.Clear();
            while (copyList.Count > 0)
            {
                int rdIndex = Range(0, copyList.Count - 1);
                T remove = copyList[rdIndex];

                copyList.Remove(remove);
                inputList.Add(remove);
            }
        }


        /// <summary>
        ///  获得一个数组打乱后的结果 (复制)
        /// </summary>
        /// <param name="inputList">输入的数组</param>
        /// <typeparam name="T">数组类型</typeparam>
        /// <returns>输出的数组</returns>
        public static IList<T> Shuffle<T>(IList<T> inputList)
        {
            T[] copyArray = inputList.ToArray();
            List<T> copyList = new List<T>(copyArray);
            List<T> outputList = new List<T>();
            while (copyList.Count > 0)
            {
                int rdIndex = Range(0, copyList.Count - 1);
                T remove = copyList[rdIndex];

                copyList.Remove(remove);
                outputList.Add(remove);
            }
            return outputList;
        }


        static public T List<T>(IList<T> list)
        {
            if (list.Count <= 0) return default(T);
            if (list.Count <= 1) return list[0];
            var index = Range(0, list.Count);
            return list[index];
        }

        public static T ListWeight<T>(IList<T> list, IList<int> weights)
        {
            if (list.Count <= 0) return default(T);
            if (list.Count <= 1) return list[0];
            var index = WeightIndex(weights, list.Count);
            if (index == -1 || index > list.Count - 1) index = list.Count - 1;
            return list[index];
        }


        public static IList<T> ListMult<T>(IList<T> list, int count = 1)
        {
            IList<T> _list = new List<T>(list);
            IList<T> resList = new List<T>();
            if (list.Count <= 1) return _list;
            if (count > list.Count) count = list.Count;
            for (int j = 0; j < count; j++)
            {
                int id = Range(0, _list.Count);
                var res = _list[id];
                resList.Add(res);
                _list.RemoveAt(id);
            }
            return resList;
        }

        public static IList<T> ListMultWeight<T>(IList<T> list, IList<int> weights, int count = 1)
        {
            IList<T> _list = new List<T>(list);
            IList<int> _weights = new List<int>(weights);

            IList<T> resList = new List<T>();

            if (list.Count <= 1) return _list;
            if (count > list.Count) count = list.Count;

            for (int j = 0; j < count; j++)
            {
                int id = WeightIndex(_weights, _list.Count);//权重随机

                //保留结果
                if (id >= _weights.Count - 1)
                {
                    id = _weights.Count - 1; //防止超界
                }

                var res = _list[id];
                resList.Add(res);

                _weights.RemoveAt(id); //移除对应权重
                _list.RemoveAt(id); //移除对应权重

            }
            return resList;
        }


        static public T Array<T>(T[] list)
        {
            if (list.Length <= 0) return default(T);
            if (list.Length <= 1) return list[0];
            var index = Range(0, list.Length);
            return list[index];
        }


        static public int[] SplitInt(int sum, int piece = 2)
        {
            List<int> arrayTemp = new List<int> { };
            if (piece > 1)
            {
                int fSumTmp = sum;
                int iAcc = 0;
                for (var i = 0; i < (piece - 1); i++)
                {
                    var iTmp = Mathf.CeilToInt(Range(0, 1.0f) * (fSumTmp / 2));
                    arrayTemp.Insert(0, iTmp);
                    fSumTmp -= iTmp;
                    iAcc += iTmp;
                }
                arrayTemp.Insert(0, sum - iAcc);
            }
            else
            {
                arrayTemp.Insert(0, sum);
            }

            return arrayTemp.ToArray();
        }

        static public float[] SplitFloat(float sum, int piece = 2)
        {
            List<float> arrayTemp = new List<float> { };
            if (piece > 1)
            {
                float fSumTmp = sum;
                float tSum = 0;

                for (int i = 0; i < piece; i++)
                {
                    float temp = Range(0, 1.0f);
                    arrayTemp.Insert(0, temp);
                    tSum += temp;
                }

                for (int i = 0; i < piece; i++)
                {
                    arrayTemp[i] = arrayTemp[i] * sum / tSum;
                }

            }
            else
            {
                arrayTemp.Insert(0, sum);
            }

            return arrayTemp.ToArray();
        }

        static public Vector2 Circle2D(float radius)
        {
            return Circle2D(0, radius);
        }

        static public Vector2 Circle2D(float rMin, float rMax)
        {
            var r = Range(rMin, rMax);
            float a = Range(0, Mathf.PI * 2);
            return new Vector2(r * Mathf.Cos(a), r * Mathf.Sin(a));
        }

        static public Vector3 Circle3D(float rMin, float rMax, Vector3 direction = default)
        {
            var v2 = Circle2D(rMin, rMax);
            if (direction.Equals(Vector3.up) || direction.Equals(Vector3.down))
            {
                return new Vector3(v2.x, 0, v2.y);
            }
            else if (direction.Equals(Vector3.forward) || direction.Equals(Vector3.back))
            {
                return new Vector3(v2.x, v2.y, 0);
            }
            else
            {
                return new Vector3(v2.x, v2.y, 0);
            }

        }


    }


}
